package com.hup.sidebar.framework.util;

import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;

import androidx.annotation.NonNull;

/**
 * @author hugan
 * @date 2022/6/7
 */
public class IconUtil {

    /**
     * 缩放图像,描边
     * - 描边模式: "内容内缩描边", 目标图像尺寸不变, 原图像缩小画在描边内; (与[内描边]区别是, 内描边会遮盖原图)
     * - 方案: 用borderColor填充原图不透明像素, 再内缩绘制原图; 核心[适合各种不规则轮廓图像], 简单高效的,避免多次绘制,或创建Bitmap,
     *
     * @param src 目前只支持特定来源的对象!
     * @param scale 缩放比例
     */
    public static Bitmap resizeIconWithStroke(@NonNull Drawable src, float scale, int borderPx, int borderColor) {
        int srcW = src.getIntrinsicWidth();
        int srcH = src.getIntrinsicHeight();
        if (srcW <= 0 || srcH <= 0 || borderPx < 0) {
            throw new IllegalArgumentException("入参异常");
        }

        //复制对象,否则setBounds 会修改全局共享的drawable
        src = src.getConstantState().newDrawable().mutate();

        int width = (int) (srcW * scale);
        int height = (int) (srcH * scale);
        Bitmap res = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(res);

        // 绘制缩放后的原图
        Rect full = new Rect(0, 0, width, height);
        src.setBounds(full);
        src.draw(canvas);

        // 用边框色覆盖不透明区域
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(borderColor);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));
        canvas.drawRect(0, 0, width, height, paint);
        paint.setXfermode(null);

        // 再画一次缩小后的原图; borderPx大于原图时不报错
        Rect inset = new Rect(borderPx, borderPx, width - borderPx, height - borderPx);
        src.setBounds(inset);
        src.draw(canvas);

        return res;
    }

    /**
     * @return 可以编辑, recycled的图像
     * @apiNote 这里有不少坑, 涉及安卓的bitmap/drawable复用共享等
     */
    public static Bitmap getBitmapEditable(Drawable drawable) {
        /*
        R.drawable.xxx的BitmapDrawable是全局共享的, 不能直接返回它! 避免被业务代码recycle
         if (drawable instanceof BitmapDrawable) return ((BitmapDrawable) drawable).getBitmap();
         */
        if (drawable instanceof BitmapDrawable) {
            Bitmap src = ((BitmapDrawable) drawable).getBitmap();
            if (src != null) {
                /*
                - 返回一个可修改的副本（或用 false 来返回只读副本）
                - src是全局共享的,不能直接返回, 避免调用了 recycle等方法
                - copy的性能等, 比下面的方式好
                 */
                return src.copy(src.getConfig() != null ? src.getConfig() : Config.ARGB_8888, true);
            }
        }

        /*
        - drawable.setBounds(0, 0, w, h); 是会影响原图的, 所以需要newDrawable().mutate()
        - drawable.mutate()也是不安全的, 也会修改原图
        - getConstantState在很多场景下会null
        - drawable.get/setBounds的还原方式,也是不安全的!
         */
        drawable = (drawable.getConstantState() != null) ? drawable.getConstantState().newDrawable().mutate() : drawable.mutate();

        int w = Math.max(1, drawable.getIntrinsicWidth());
        int h = Math.max(1, drawable.getIntrinsicHeight());

        Bitmap bitmap = Bitmap.createBitmap(w, h, Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, w, h);
        drawable.draw(canvas);
        return bitmap;
    }


}
